<template>
  <div class="menu-management">
    <el-card>
      <template #header>
        <div class="card-header">
          <span>菜单管理</span>
          <el-button type="primary" @click="handleAdd">
            <el-icon><Plus /></el-icon>
            新增菜单
          </el-button>
        </div>
      </template>

      <!-- 搜索表单 -->
      <el-form :inline="true" :model="searchForm" class="search-form">
        <el-form-item label="菜单名称">
          <el-input v-model="searchForm.menuName" placeholder="请输入菜单名称" clearable />
        </el-form-item>
        <el-form-item label="菜单类型">
          <el-select v-model="searchForm.menuType" placeholder="请选择菜单类型" clearable>
            <el-option label="目录" value="M" />
            <el-option label="菜单" value="C" />
            <el-option label="按钮" value="F" />
          </el-select>
        </el-form-item>
        <el-form-item label="状态">
          <el-select v-model="searchForm.status" placeholder="请选择状态" clearable>
            <el-option label="启用" :value="0" />
            <el-option label="禁用" :value="1" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleSearch">
            <el-icon><Search /></el-icon>
            搜索
          </el-button>
          <el-button @click="handleReset">
            <el-icon><Refresh /></el-icon>
            重置
          </el-button>
        </el-form-item>
      </el-form>

      <!-- 菜单树形表格 -->
      <el-table 
        :data="menuTree" 
        style="width: 100%" 
        v-loading="loading"
        row-key="id"
        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
        default-expand-all
        @row-drag-end="handleRowDragEnd"
        draggable
      >
        <el-table-column prop="menuName" label="菜单名称" min-width="200">
          <template #default="{ row }">
            <el-icon v-if="row.icon" class="menu-icon">
              <component :is="row.icon" />
            </el-icon>
            <span>{{ row.menuName }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="menuType" label="菜单类型" width="100">
          <template #default="{ row }">
            <el-tag :type="getMenuTypeTag(row.menuType)">
              {{ getMenuTypeText(row.menuType) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="path" label="路由地址" width="150" show-overflow-tooltip />
        <el-table-column prop="component" label="组件路径" width="200" show-overflow-tooltip />
        <el-table-column prop="permission" label="权限标识" width="150" />
        <el-table-column prop="sort" label="排序" width="80">
          <template #default="{ row }">
            <el-tag type="info">{{ row.sort }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="status" label="状态" width="80">
          <template #default="{ row }">
            <el-tag :type="row.status === 0 ? 'success' : 'danger'">
              {{ row.status === 0 ? '启用' : '禁用' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="250" fixed="right">
          <template #default="{ row }">
            <el-button type="primary" link @click="handleEdit(row)">编辑</el-button>
            <el-button 
              :type="row.status === 0 ? 'danger' : 'success'" 
              link 
              @click="handleToggleStatus(row)"
            >
              {{ row.status === 0 ? '禁用' : '启用' }}
            </el-button>
            <el-button type="info" link @click="handleSort(row)">
              <el-icon><Sort /></el-icon>
              排序
            </el-button>
            <el-button type="danger" link @click="handleDelete(row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <!-- 新增/编辑菜单对话框 -->
    <el-dialog
      v-model="dialogVisible"
      :title="dialogTitle"
      width="600px"
      @close="handleDialogClose"
    >
      <el-form
        ref="menuFormRef"
        :model="menuForm"
        :rules="menuRules"
        label-width="100px"
      >
        <el-form-item label="上级菜单" prop="parentId">
          <el-tree-select
            v-model="menuForm.parentId"
            :data="parentMenuOptions"
            :props="{ label: 'menuName', value: 'id', children: 'children' }"
            placeholder="请选择上级菜单"
            clearable
            check-strictly
          />
        </el-form-item>
        <el-form-item label="菜单类型" prop="menuType">
          <el-radio-group v-model="menuForm.menuType">
            <el-radio label="M">目录</el-radio>
            <el-radio label="C">菜单</el-radio>
            <el-radio label="F">按钮</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="菜单名称" prop="menuName">
          <el-input v-model="menuForm.menuName" placeholder="请输入菜单名称" maxlength="50" show-word-limit />
        </el-form-item>
        <el-form-item label="菜单图标" prop="icon" v-if="menuForm.menuType !== 'F'">
          <div class="icon-selector">
            <el-input v-model="menuForm.icon" placeholder="请选择或输入图标名称" readonly>
              <template #prefix>
                <el-icon v-if="menuForm.icon" class="selected-icon">
                  <component :is="menuForm.icon" />
                </el-icon>
              </template>
              <template #suffix>
                <el-button link @click="showIconDialog = true">
                  <el-icon><Search /></el-icon>
                </el-button>
              </template>
            </el-input>
          </div>
        </el-form-item>
        <el-form-item label="路由地址" prop="path" v-if="menuForm.menuType !== 'F'">
          <el-input v-model="menuForm.path" placeholder="请输入路由地址" maxlength="100" show-word-limit />
        </el-form-item>
        <el-form-item label="组件路径" prop="component" v-if="menuForm.menuType === 'C'">
          <el-input v-model="menuForm.component" placeholder="请输入组件路径" maxlength="100" show-word-limit />
        </el-form-item>
        <el-form-item label="权限标识" prop="permission" v-if="menuForm.menuType === 'F'">
          <el-select v-model="menuForm.permission" placeholder="请选择权限标识" clearable filterable allow-create>
            <el-option label="新增" value="add" />
            <el-option label="编辑" value="edit" />
            <el-option label="删除" value="delete" />
            <el-option label="查询" value="query" />
            <el-option label="导出" value="export" />
            <el-option label="导入" value="import" />
            <el-option label="审核" value="audit" />
            <el-option label="发布" value="publish" />
          </el-select>
          <div class="permission-tips">
            <el-icon><InfoFilled /></el-icon>
            <span>权限标识格式：模块:操作，如：user:add</span>
          </div>
        </el-form-item>
        <el-form-item label="排序" prop="sort">
          <el-input-number v-model="menuForm.sort" :min="0" :max="999" />
        </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-radio-group v-model="menuForm.status">
            <el-radio :label="0">启用</el-radio>
            <el-radio :label="1">禁用</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="submitLoading" @click="handleSubmit">
          确定
        </el-button>
      </template>
    </el-dialog>

    <!-- 图标选择器对话框 -->
    <el-dialog
      v-model="showIconDialog"
      title="选择图标"
      width="600px"
      @close="handleIconDialogClose"
    >
      <div class="icon-grid">
        <div
          v-for="icon in availableIcons"
          :key="icon"
          class="icon-item"
          :class="{ active: icon === menuForm.icon }"
          @click="selectIcon(icon)"
        >
          <el-icon class="icon-preview">
            <component :is="icon" />
          </el-icon>
          <span class="icon-name">{{ icon }}</span>
        </div>
      </div>
      <template #footer>
        <el-button @click="showIconDialog = false">取消</el-button>
        <el-button type="primary" @click="confirmIconSelection">确定</el-button>
      </template>
    </el-dialog>

    <!-- 排序对话框 -->
    <el-dialog
      v-model="sortDialogVisible"
      title="菜单排序"
      width="400px"
      @close="handleSortDialogClose"
    >
      <div class="sort-content">
        <el-alert
          title="拖拽下方菜单项进行排序"
          type="info"
          :closable="false"
          style="margin-bottom: 15px;"
        />
        <div class="sortable-list">
          <div
            v-for="(item, index) in sortableMenus"
            :key="item.id"
            class="sortable-item"
            draggable="true"
            @dragstart="handleDragStart($event, index)"
            @dragover.prevent
            @drop="handleDrop($event, index)"
          >
            <el-icon class="drag-handle"><Rank /></el-icon>
            <el-icon v-if="item.icon" class="item-icon">
              <component :is="item.icon" />
            </el-icon>
            <span class="item-name">{{ item.menuName }}</span>
            <el-tag size="small" :type="getMenuTypeTag(item.menuType)">
              {{ getMenuTypeText(item.menuType) }}
            </el-tag>
          </div>
        </div>
      </div>
      <template #footer>
        <el-button @click="sortDialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="sortLoading" @click="saveSortOrder">
          保存排序
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue'
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus'
import { Search, Refresh, Plus, Rank, Sort, InfoFilled } from '@element-plus/icons-vue'
import {
  getMenuPage,
  createMenu,
  updateMenu,
  deleteMenu,
  updateMenuStatus
} from '@/api/system'
import type { Menu, MenuListParams } from '@/types/api'

const loading = ref(false)
const menuTree = ref<Menu[]>([])
const allMenus = ref<Menu[]>([])

const searchForm = reactive({
  menuName: '',
  menuType: '',
  status: undefined as number | undefined
})

const dialogVisible = ref(false)
const submitLoading = ref(false)
const menuFormRef = ref<FormInstance>()
const showIconDialog = ref(false)
const sortDialogVisible = ref(false)
const sortLoading = ref(false)
const sortableMenus = ref<Menu[]>([])
const draggedIndex = ref<number | null>(null)

const menuForm = reactive({
  id: undefined as number | undefined,
  parentId: 0,
  menuName: '',
  menuType: 'M',
  icon: '',
  path: '',
  component: '',
  permission: '',
  sort: 0,
  status: 0
})

const menuRules: FormRules = {
  menuName: [
    { required: true, message: '请输入菜单名称', trigger: 'blur' },
    { min: 2, max: 50, message: '菜单名称长度应在2-50个字符之间', trigger: 'blur' }
  ],
  menuType: [{ required: true, message: '请选择菜单类型', trigger: 'change' }],
  path: [
    { required: true, message: '请输入路由地址', trigger: 'blur' },
    { pattern: /^\/[a-zA-Z0-9-_\/]*$/, message: '路由地址应以/开头，只能包含字母、数字、-和_', trigger: 'blur' }
  ],
  component: [
    { required: true, message: '请输入组件路径', trigger: 'blur' },
    { pattern: /^[a-zA-Z0-9-_\/]+$/, message: '组件路径只能包含字母、数字、-、_和/', trigger: 'blur' }
  ],
  permission: [
    { required: true, message: '请输入权限标识', trigger: 'blur' },
    { pattern: /^[a-zA-Z0-9:_]+$/, message: '权限标识只能包含字母、数字、:和_', trigger: 'blur' }
  ]
}

const parentMenuOptions = computed(() => {
  const options = [{ id: 0, menuName: '顶级菜单', children: [] }]
  if (allMenus.value.length > 0) {
    options.push(...buildMenuTree(allMenus.value))
  }
  return options
})

const dialogTitle = computed(() => 
  menuForm.id ? '编辑菜单' : '新增菜单'
)

const getMenuTypeText = (type: string) => {
  const typeMap = {
    'M': '目录',
    'C': '菜单',
    'F': '按钮'
  }
  return typeMap[type as keyof typeof typeMap] || type
}

const getMenuTypeTag = (type: string) => {
  const tagMap = {
    'M': 'primary',
    'C': 'success',
    'F': 'warning'
  }
  return tagMap[type as keyof typeof tagMap] || 'info'
}

const fetchMenuList = async () => {
  loading.value = true
  try {
    const params: MenuListParams = {
      menuName: searchForm.menuName,
      menuCode: undefined,
      status: searchForm.status
    }
    // 移除空值参数
    Object.keys(params).forEach(key => {
      if (params[key] === '' || params[key] === null || params[key] === undefined) {
        delete params[key]
      }
    })
    const response = await getMenuPage(params)
    allMenus.value = response.records || response
    menuTree.value = buildMenuTree(allMenus.value)
  } catch (error) {
    ElMessage.error('获取菜单列表失败')
  } finally {
    loading.value = false
  }
}

const buildMenuTree = (menus: any[]): any[] => {
  const menuMap = new Map<number, any>()
  const result: any[] = []

  // 创建菜单映射
  menus.forEach(menu => {
    menuMap.set(menu.id, { ...menu, children: menu.children || [] })
  })

  // 构建树形结构
  menus.forEach(menu => {
    const menuItem = menuMap.get(menu.id)!
    if (menu.parentId === 0 || !menu.parentId) {
      result.push(menuItem)
    } else {
      const parent = menuMap.get(menu.parentId)
      if (parent) {
        parent.children = parent.children || []
        parent.children.push(menuItem)
      }
    }
  })

  return result
}

const loadMenuList = async (params?: MenuListParams) => {
  loading.value = true
  try {
    const searchParams: MenuListParams = params || {
      menuName: searchForm.menuName || undefined,
      menuCode: undefined,
      status: searchForm.status
    }
    const response = await getMenuPage(searchParams)
    allMenus.value = response
    menuTree.value = buildMenuTree(allMenus.value)
  } catch (error) {
    ElMessage.error('获取菜单列表失败')
  } finally {
    loading.value = false
  }
}

const handleSearch = () => {
  const params: MenuListParams = {
    menuName: searchForm.menuName || undefined,
    menuCode: undefined,
    status: searchForm.status
  }
  loadMenuList(params)
}

const handleReset = () => {
  searchForm.menuName = ''
  searchForm.menuType = ''
  searchForm.status = undefined
  fetchMenuList()
}

onMounted(() => {
  fetchMenuList()
})

const handleAdd = () => {
  menuForm.id = undefined
  menuForm.parentId = 0
  menuForm.menuName = ''
  menuForm.menuType = 'M'
  menuForm.icon = ''
  menuForm.path = ''
  menuForm.component = ''
  menuForm.permission = ''
  menuForm.sort = 0
  menuForm.status = 0
  dialogVisible.value = true
}

const handleEdit = (row: Menu) => {
  menuForm.id = row.id
  menuForm.parentId = row.parentId
  menuForm.menuName = row.menuName
  menuForm.menuType = row.menuType
  menuForm.icon = row.icon || ''
  menuForm.path = row.path || ''
  menuForm.component = row.component || ''
  menuForm.permission = row.permission || ''
  menuForm.sort = row.sort
  menuForm.status = row.status
  dialogVisible.value = true
}

const handleToggleStatus = async (row: Menu) => {
  try {
    await ElMessageBox.confirm(
      `确定要${row.status === 0 ? '禁用' : '启用'}菜单"${row.menuName}"吗？`,
      '提示',
      { type: 'warning' }
    )
    
    await updateMenuStatus(row.id, row.status === 0 ? 1 : 0)
    ElMessage.success(`${row.status === 0 ? '禁用' : '启用'}成功`)
    fetchMenuList()
  } catch (error) {
    if (error !== 'cancel') {
      ElMessage.error('操作失败')
    }
  }
}

const handleDelete = async (row: Menu) => {
  try {
    await ElMessageBox.confirm(
      `确定要删除菜单"${row.menuName}"吗？`,
      '提示',
      { type: 'warning' }
    )
    
    await deleteMenu(row.id)
    ElMessage.success('删除成功')
    fetchMenuList()
  } catch (error) {
    if (error !== 'cancel') {
      ElMessage.error('删除失败')
    }
  }
}

// 排序功能
const handleSort = (row: Menu) => {
  // 获取同级菜单进行排序
  const parentId = row.parentId || 0
  const siblingMenus = allMenus.value.filter(menu => (menu.parentId || 0) === parentId)
  sortableMenus.value = siblingMenus.sort((a, b) => a.sort - b.sort)
  sortDialogVisible.value = true
}

const handleDragStart = (event: DragEvent, index: number) => {
  draggedIndex.value = index
  if (event.dataTransfer) {
    event.dataTransfer.effectAllowed = 'move'
  }
}

const handleDrop = (event: DragEvent, dropIndex: number) => {
  event.preventDefault()
  if (draggedIndex.value === null) return
  
  const draggedItem = sortableMenus.value[draggedIndex.value]
  sortableMenus.value.splice(draggedIndex.value, 1)
  sortableMenus.value.splice(dropIndex, 0, draggedItem)
  draggedIndex.value = null
}

const saveSortOrder = async () => {
  try {
    sortLoading.value = true
    // 更新排序值
    const updatePromises = sortableMenus.value.map((menu, index) => {
      return updateMenu(menu.id, { ...menu, sort: index })
    })
    
    await Promise.all(updatePromises)
    ElMessage.success('排序更新成功')
    sortDialogVisible.value = false
    fetchMenuList()
  } catch (error) {
    ElMessage.error('排序更新失败')
  } finally {
    sortLoading.value = false
  }
}

const handleSortDialogClose = () => {
  sortableMenus.value = []
  draggedIndex.value = null
}

// 图标选择功能
const selectIcon = (icon: string) => {
  selectedIcon.value = icon
}

const confirmIconSelection = () => {
  menuForm.icon = selectedIcon.value
  showIconDialog.value = false
}

const handleIconDialogClose = () => {
  selectedIcon.value = ''
}

const handleSubmit = async () => {
  if (!menuFormRef.value) return
  
  try {
    await menuFormRef.value.validate()
    submitLoading.value = true
    
    if (menuForm.id) {
      await updateMenu(menuForm.id, menuForm)
      ElMessage.success('更新成功')
    } else {
      await createMenu(menuForm)
      ElMessage.success('创建成功')
    }
    
    dialogVisible.value = false
    fetchMenuList()
  } catch (error) {
    if (error !== 'cancel') {
      ElMessage.error('操作失败')
    }
  } finally {
    submitLoading.value = false
  }
}

const handleDialogClose = () => {
  menuFormRef.value?.resetFields()
}

// 可用图标列表
const availableIcons = ref([
  'House', 'User', 'Setting', 'Lock', 'Key', 'Menu', 'Document',
  'Folder', 'FolderOpened', 'Edit', 'Delete', 'Search', 'Refresh',
  'Plus', 'Minus', 'Check', 'Close', 'ArrowRight', 'ArrowLeft',
  'ArrowUp', 'ArrowDown', 'Star', 'Collection', 'Upload', 'Download',
  'Calendar', 'Clock', 'Message', 'Bell', 'Phone', 'Email',
  'Location', 'Picture', 'Video', 'Music', 'Camera', 'Printer',
  'Monitor', 'Mobile', 'Tablet', 'Laptop', 'Desktop', 'Server',
  'Database', 'Cloud', 'Network', 'Security', 'Shield', 'Warning',
  'Info', 'Question', 'Success', 'Error', 'Loading', 'Rank'
])

const selectedIcon = ref('')
</script>

<style scoped>
.menu-management {
  padding: 20px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.search-form {
  margin-bottom: 20px;
  padding: 20px;
  background: #f5f7fa;
  border-radius: 4px;
}

.menu-icon {
  margin-right: 8px;
  vertical-align: middle;
}

.icon-selector {
  width: 100%;
}

.selected-icon {
  font-size: 16px;
  margin-right: 8px;
}

.icon-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  gap: 10px;
  max-height: 400px;
  overflow-y: auto;
}

.icon-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 12px;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s;
}

.icon-item:hover {
  background-color: #f5f7fa;
  border-color: #409eff;
}

.icon-item.active {
  background-color: #ecf5ff;
  border-color: #409eff;
  color: #409eff;
}

.icon-preview {
  font-size: 24px;
  margin-bottom: 5px;
}

.icon-name {
  font-size: 12px;
  text-align: center;
  word-break: break-all;
}

.sort-content {
  padding: 10px 0;
}

.sortable-list {
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  max-height: 300px;
  overflow-y: auto;
}

.sortable-item {
  display: flex;
  align-items: center;
  padding: 12px;
  border-bottom: 1px solid #f0f2f5;
  cursor: move;
  transition: background-color 0.3s;
}

.sortable-item:hover {
  background-color: #f5f7fa;
}

.sortable-item:last-child {
  border-bottom: none;
}

.drag-handle {
  margin-right: 10px;
  color: #909399;
  cursor: move;
}

.item-icon {
  margin-right: 8px;
  font-size: 16px;
}

.item-name {
  flex: 1;
  margin-right: 10px;
}

.permission-tips {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-top: 5px;
  font-size: 12px;
  color: #909399;
}

@media (max-width: 768px) {
  .icon-grid {
    grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
  }
  
  .icon-item {
    padding: 8px;
  }
  
  .icon-preview {
    font-size: 20px;
  }
}
</style>